namespace OpenComposite.EII
{
	using System;
	using System.Data.SqlClient;
	using System.Drawing;
	using System.Windows.Forms;
	using System.Xml;
	using System.Xml.Schema;
	using OpenComposite.Forms;
	using OpenComposite.Repository.Properties;
	using OpenComposite.EII.Repository;
	using OpenComposite.EII.RepositoryUIs;
	using WeifenLuo.WinFormsUI.Docking;
	using OpenComposite.Repository.Interfaces;

	public partial class formDomainEditor : DockContent
	{
		#region Initialization

		public formDomainEditor(IServiceProvider serviceProvider)
		{
			this.UpdateItem = null;
			this.CreateProcessForMethod = null;

			_serviceProvider = serviceProvider;

			InitializeComponent();

			init();
		}

		#endregion Initialization

		#region Public Members

		#region Events

		public event EventHandler<ItemSelectedEventArgs> CreateProcessForMethod;

		public event EventHandler<ItemSelectedEventArgs> UpdateItem;

		#endregion Events

		#region Methods

		public void DeleteItem(TreeNode node)
		{
			showDetails(node);
			deleteCurrent();
		}

		public void ShowItem(TreeNode node)
		{
			showDetails(node);
		}

		public void ShowItem(ItemType type, int id)
		{
			showDetails(type, id);
		}

		#endregion Methods

		#endregion Public Members

		#region Protected Members

		#region Methods

		protected override object GetService(Type service)
		{
			return _serviceProvider.GetService(service);
		}

		protected override void OnFormClosed(FormClosedEventArgs e)
		{
			if ( _itemui != null && !_itemui.ReadOnly ) {
				RepositoryItemBaseEx itemex = _itemui.RepositoryItem as RepositoryItemBaseEx;
				if ( itemex != null ) itemex.UnlockFromCurrentUser();
			}
			base.OnFormClosed(e);
		}

		#endregion Methods

		#endregion Protected Members

		#region Private Members

		#region Fields

		private IRepositoryItem _currentItem = null;
		private RepositoryItemUI _itemui = null;

		//private UCDomain _ucdomain = null;
		//private UCService _ucservice = null;
		//private UCOperation _ucoperation = null;
		//private UCNoun _ucnoun = null;
		//private ucRuleEditor _ucruleeditor = null;
		//private UCBObject _ucbobject = null;
		//private UCVerb _ucverb = null;
		//private UCFolder _ucfolder = null;
		//private UCBPolicy _ucbpolicy = null;
		private IServiceProvider _serviceProvider;
		private TreeNode _tnCurrent = null;

		#endregion Fields

		#region Event Handlers

		private void FormMain_Load(object sender, EventArgs e)
		{
			//ucSystemConfig1.Mapper.SourceSchema = loadSchema(@"D:\Projekte\PROJECTS\IT_SYSTEME\Mapper\Source.xsd");
			//ucSystemConfig1.Mapper.TargetSchema = loadSchema(@"D:\Projekte\PROJECTS\IT_SYSTEME\Mapper\Target.xsd");
		}

		private void btnOK_Click(object sender, EventArgs e)
		{
			saveCurrent();
		}

		private void closeAllButThisToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Helpers.CloseAllWindows(this.DockPanel);
		}

		private void formDomainEditor_DockStateChanged(object sender, EventArgs e)
		{
			if ( _itemui != null && _itemui is UCDocumentation ) {
				_itemui.RepositoryItem = _itemui.RepositoryItem;
			}
		}

		private void tsbtnDelete_Click(object sender, EventArgs e)
		{
			deleteCurrent();
		}

		private void tsbtnSave_Click(object sender, EventArgs e)
		{
			saveCurrent();
		}

		private void ucTrees1_CreateProcessForMethod(object sender, ItemSelectedEventArgs e)
		{
			EventHandler<ItemSelectedEventArgs> tmp = this.CreateProcessForMethod;
			if ( tmp != null )
				tmp(sender, e);
		}

		private void ucTrees1_DeleteItem(object sender, ItemSelectedEventArgs e)
		{
			showDetails(e.Node);
			deleteCurrent();
		}

		private void ucTrees1_ItemSelected(object sender, ItemSelectedEventArgs e)
		{
			if ( e.Node == null && e.Type == ItemType.Repository ) {
				showDetails(e.Type, e.RepositoryId);
			} else {
				showDetails(e.Node);
			}
		}

		private void xmlschemaread_ValidationCallback(object sender, ValidationEventArgs e)
		{
			MessageBox.Show(e.Message, e.Exception.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
		}

		#endregion Event Handlers

		#region Methods

		private void deleteCurrent()
		{
			if ( _currentItem == null ) return;
			try {
				if ( _currentItem.Delete(true) ) {
					_currentItem = null;
					_tnCurrent.Remove();
				}
			} catch ( SqlException sqlex ) {
				MessageBox.Show(sqlex.Message, "Database Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void init()
		{
			#region Old Code
			////
			//// _ucdomain
			////
			//_ucdomain = new UCDomain();
			//_ucdomain.Location = new Point(0, 0);
			//_ucdomain.Visible = false;
			//_ucdomain.Dock = DockStyle.Fill;
			////
			//// _ucservice
			////
			//_ucservice = new UCService();
			//_ucservice.Location = new Point(0, 0);
			//_ucservice.Visible = false;
			//_ucservice.Dock = DockStyle.Fill;
			////
			//// _ucmethod
			////
			//_ucoperation = new UCOperation();
			//_ucoperation.Location = new Point(0, 0);
			//_ucoperation.Visible = false;
			//_ucoperation.Dock = DockStyle.Fill;
			////
			//// _ucgvariable
			////
			//_ucnoun = new UCNoun();
			//_ucnoun.Location = new Point(0, 0);
			//_ucnoun.Visible = false;
			//_ucnoun.Dock = DockStyle.Fill;
			////
			//// _ucruleeditor
			////
			//_ucruleeditor = new ucRuleEditor();
			//_ucruleeditor.Location = new Point(0, 0);
			//_ucruleeditor.Visible = false;
			//_ucruleeditor.Dock = DockStyle.Fill;
			//_ucruleeditor.SetConnectString(Global.Data.ProcessData.ConnectString);
			//_ucruleeditor.SetOrgid(Global.Data.ProcessData.UserData.OrganizationID);
			////
			//// _ucbobject
			////
			//_ucbobject = new UCBObject();
			//_ucbobject.Location = new Point(0, 0);
			//_ucbobject.Visible = false;
			//_ucbobject.Dock = DockStyle.Fill;
			////
			//// _ucverb
			////
			//_ucverb = new UCVerb();
			//_ucverb.Location = new Point(0, 0);
			//_ucverb.Visible = false;
			//_ucverb.Dock = DockStyle.Fill;
			////
			//// _ucfolder
			////
			//_ucfolder = new UCFolder();
			//_ucfolder.Location = new Point(0, 0);
			//_ucfolder.Visible = false;
			//_ucfolder.Dock = DockStyle.Fill;
			////
			//// _ucbpolicy
			////
			//_ucbpolicy = new UCBPolicy();
			//_ucbpolicy.Location = new Point(0, 0);
			//_ucbpolicy.Visible = false;
			//_ucbpolicy.Dock = DockStyle.Fill;

			//pnlDetails.Controls.Add(_ucdomain);
			//pnlDetails.Controls.Add(_ucservice);
			//pnlDetails.Controls.Add(_ucoperation);
			//pnlDetails.Controls.Add(_ucnoun);
			//pnlDetails.Controls.Add(_ucruleeditor);
			//pnlDetails.Controls.Add(_ucbobject);
			//pnlDetails.Controls.Add(_ucverb);
			//pnlDetails.Controls.Add(_ucfolder);
			//pnlDetails.Controls.Add(_ucbpolicy);
			#endregion

			showDetails(null);
			//Global.Data.CheckBRuleRootCategories();

			this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
			this.SetStyle(ControlStyles.ResizeRedraw, false);
			this.UpdateStyles();
		}

		private XmlSchema loadSchema(string filename)
		{
			XmlSchema xsd = null;
			using ( XmlTextReader xr = new XmlTextReader(filename) ) {
				xsd = XmlSchema.Read(xr, new ValidationEventHandler(xmlschemaread_ValidationCallback));
			}
			return xsd;
		}

		private void onUpdateItem(ItemType type, TreeNode node)
		{
			int repid = -1;
			if ( type == ItemType.Repository )
				repid = _currentItem.ID;
			else if ( node != null && node.TreeView != null )
				repid = ( (Repository.RepositoryObject)node.TreeView.Tag ).ID;
			EventHandler<ItemSelectedEventArgs> tmp = this.UpdateItem;
			if ( tmp != null )
				tmp(this, new ItemSelectedEventArgs(type, node, repid));
		}

		private void saveCurrent()
		{
			if ( _currentItem == null ) return;

			bool bUpdateNode = false;
			try {
				if ( _itemui != null ) {
					try {
						bUpdateNode = _itemui.RepositoryItem.Save();
					} catch ( RepositoryItemDeletedException ) {
						bUpdateNode = false;
					}
				}
				if ( bUpdateNode ) onUpdateItem(_currentItem.RepositoryItemType, _tnCurrent);
			} catch ( SqlException sqlex ) {
				string msg = string.Format(
					"There is a problem with the connection to the database.{0}{0}" +
					"Please check your database connection and try again.", Environment.NewLine);
				ErrorBox.Show(msg, "Database Error", sqlex.Message, false);
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
		private void saveItem(IRepositoryItem item)
		{
			if ( item == null ) return;

			bool bUpdateNode = false;
			try {
				try {
					bUpdateNode = item.Save();
				} catch ( RepositoryItemDeletedException ) {
					bUpdateNode = false;
				}
				if ( bUpdateNode ) onUpdateItem(item.RepositoryItemType, _tnCurrent);
			} catch ( SqlException sqlex ) {
				string msg = string.Format(
					"There is a problem with the connection to the database.{0}{0}" +
					"Please check your database connection and try again.", Environment.NewLine);
				ErrorBox.Show(msg, "Database Error", sqlex.Message, false);
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void showDetails(TreeNode node)
		{
			this.SuspendLayout();
			//pnlDetails.SuspendLayout();

			Cursor.Current = Cursors.WaitCursor;
			setTabDefaults();

			try {
				_tnCurrent = node;
				_currentItem = null;

				ItemType type = ItemType.Undefined;
				RepositoryItemBase item = null;
				if ( node != null ) {
					item = node.Tag as RepositoryItemBase;
				}
				if ( item != null )
					type = item.RepositoryItemType;

				_currentItem = item;

				showItemUI(item);
			} catch ( RepositoryItemDeletedException ) {
				node.Remove();
			} catch ( SqlException sqlex ) {
				string msg = string.Format(
					"There is a problem with the connection to the database.{0}{0}" +
					"Please check your database connection and try again.", Environment.NewLine);
				ErrorBox.Show(msg, "Database Error", sqlex.Message, false);
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
			} finally {
				Cursor.Current = Cursors.Default;
				//pnlDetails.ResumeLayout(true);
				this.ResumeLayout(true);
			}
		}

		private void showDetails(ItemType type, int id)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			pnlDetails.SuspendLayout();

			setTabDefaults();

			_tnCurrent = null;
			_currentItem = null;

			Size sizeMin = new Size(0, 0);
			IRepositoryItem item = null;
			try {
				item = repSvc.GetItem(type, id, true);
			} catch ( SqlException sqlex ) {
				string msg = string.Format(
					"There is a problem with the connection to the database.{0}{0}" +
					"Please check your database connection and try again.", Environment.NewLine);
				ErrorBox.Show(msg, "Database Error", sqlex.Message, false);
			} catch ( Exception ex ) {
				MessageBox.Show(ex.Message, "Show Details", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			_currentItem = item;

			showItemUI(item);

			pnlDetails.ResumeLayout(false);
			pnlDetails.PerformLayout();
		}

		private void showItemUI(IRepositoryItem item)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null ) throw new NullReferenceException("RepositoryService not available.");

			Size sizeMin = new Size(0, 0);
			RepositoryItemUI oldui = _itemui;
			try {
				if ( oldui != null ) {
					if ( !oldui.ReadOnly ) {
						IRepositoryItem repitem = oldui.RepositoryItem;
						RepositoryItemBaseEx olditemex = repitem as RepositoryItemBaseEx;
						bool unlockOK = true;
						if ( olditemex != null ) {
							saveItem(olditemex);
							unlockOK = olditemex.UnlockFromCurrentUser();
						} else {
							saveItem(repitem);
						}
					} else {
						oldui.ReadOnly = false;
					}
				}
				if ( item != null ) {
					_itemui = repSvc.CreateRepositoryItemUI(item.RepositoryItemType);
					if ( _itemui != null ) {

						_itemui.SuspendLayout();
						if ( !pnlDetails.Controls.Contains(_itemui) ) {
							pnlDetails.Controls.Add(_itemui);
						}
						item.Reload();
						tsDetails.Enabled = true;
						_itemui.RepositoryItem = item;

						#region Lock Item
						RepositoryItemBaseEx itemex = item as RepositoryItemBaseEx;
						if ( itemex != null ) {
							if ( !itemex.LockByCurrentUser() ) {
								User lockedByUser = itemex.GetLockedByUser();
								this.Icon = Resources.ico_lock;
								if ( lockedByUser != null ) {
									this.ToolTipText =
										String.Format("{0} \"{1}\" is locked by {2}.",
											itemex.RepositoryItemTypeName,
											itemex.Name,
											lockedByUser.FormattedName);
									IStatusService statussvc = _serviceProvider.GetService<IStatusService>();
									if ( statussvc != null ) {
										statussvc.SetStatusText(this.ToolTipText);
									}
								}
								_itemui.ReadOnly = true;
							} else {
								_itemui.ReadOnly = false;
							}
						}
						#endregion

						//tsbtnSave.Visible = _itemui.CanSave;
						tsbtnSave.Enabled = _itemui.CanSave;
						//tsbtnDelete.Visible = _itemui.CanDelete;
						tsbtnDelete.Enabled = _itemui.CanDelete;

						tslblCurrentType.Text = _itemui.TypeText;
						sizeMin = _itemui.MinimumSize;

						// activate item ui
						if ( oldui != _itemui ) {
							if ( oldui != null ) oldui.Visible = false;
							_itemui.Visible = true;
						} else {
							if ( !_itemui.Visible ) _itemui.Visible = true;
						}
						_itemui.Focus();
						this.Activate();
						_itemui.ResumeLayout(true);
						if ( this.Pane != null ) this.Pane.Refresh();
					} else {
						if ( oldui != null ) oldui.Visible = false;
					}
				} else {
					if ( oldui != null ) oldui.Visible = false;
					tsDetails.Enabled = false;
					tslblCurrentType.Text = "";
				}
				pnlDetails.AutoScrollMinSize = sizeMin;
			} catch ( System.Data.SqlClient.SqlException sqlex ) {
				if ( oldui != null ) oldui.Visible = false;
				if ( _itemui != null ) _itemui.Visible = false;
				string msg = string.Format(
					"There is a problem with the connection to the database.{0}{0}" +
					"Please check your database connection and try again.", Environment.NewLine);
				ErrorBox.Show(msg, "Database Error", sqlex.Message, false);
			} catch ( Exception ex ) {
				if ( oldui != null ) oldui.Visible = false;
				if ( _itemui != null ) _itemui.Visible = false;
				MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void setTabDefaults()
		{
			this.TabText = "Details";
			this.ToolTipText = "";
			this.Icon = Resources.ico_edit;
			IStatusService statussvc = _serviceProvider.GetService<IStatusService>();
			if ( statussvc != null ) {
				statussvc.ClearStatusText();
			}
		}

		#endregion Methods

		#endregion Private Members
	}
}